package com.example.demo.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

@Service
public class CozeService {
    private static final Logger logger = LoggerFactory.getLogger(CozeService.class);
    private static final ObjectMapper objectMapper = new ObjectMapper();

    @Value("${coze.api.url}")
    private String cozeApiUrl;

    @Value("${coze.api.key}")
    private String cozeApiKey;
    @Value("${coze.api.appId}")
    private String appId;
    @Value("${coze.api.workflowId}")
    private String workflowId;

    private final RestTemplate restTemplate;

    public CozeService() {
        // 配置RestTemplate使用UTF-8编码
        this.restTemplate = new RestTemplate();
        this.restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8));
    }

    public String askQuestion(String question) {
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("Authorization", "Bearer " + cozeApiKey);
            // 添加Accept头，明确接受text/event-stream
            headers.set(HttpHeaders.ACCEPT, "text/event-stream");
            // 明确指定UTF-8编码
            headers.setAcceptCharset(java.util.Collections.singletonList(StandardCharsets.UTF_8));

            // 直接在请求体中包含参数，避免双重编码
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("app_id", appId);
            requestBody.put("workflow_id", workflowId);

            // 创建嵌套的parameters对象
            Map<String, String> parameters = new HashMap<>();
            parameters.put("language_text", question);
            requestBody.put("parameters", parameters);

            // 打印请求体以便调试
            String requestBodyJson = objectMapper.writeValueAsString(requestBody);
            logger.info("Request body: {}", requestBodyJson);

            HttpEntity<String> entity = new HttpEntity<>(requestBodyJson, headers);

            // 将响应类型从Map改为String
            ResponseEntity<String> response = restTemplate.exchange(cozeApiUrl, HttpMethod.POST, entity, String.class);

            if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
                String responseBody = response.getBody();
                logger.debug("Raw response from Coze API: {}", responseBody);

                // 处理SSE格式的响应
                StringBuilder result = new StringBuilder();
                String[] events = responseBody.split("(?=id:)");

                for (String event : events) {
                    if (event.trim().isEmpty()) {
                        continue;
                    }
                    // 解析每个SSE事件
                    Map<String, String> eventData = parseEventData(event);
                    String data = eventData.get("data");
                    String eventType = eventData.get("event");
                    if (data != null && !data.isEmpty()&& eventType.equals("Message")) {
                        try {
                            JsonNode jsonNode = objectMapper.readTree(data);

                            // 检查是否有错误
                            if ("Error".equals(eventType) && jsonNode.has("error_message")) {
                                logger.error("Coze API error: {}", jsonNode.get("error_message").asText());
                                continue;
                            }

                            // 提取响应内容
                            if (jsonNode.has("response")) {
                                String content = jsonNode.get("response").asText();
                                result.append(decodeUnicodeIfNeeded(content));
                            } else if (jsonNode.has("content") && jsonNode.get("content").isTextual()) {
                                String content = jsonNode.get("content").asText();
                                result.append(decodeUnicodeIfNeeded(content));
                            }
                        } catch (Exception e) {
                            logger.warn("Failed to parse JSON from SSE data: {}", data, e);
                        }
                    }
                }

                if (result.length() > 0) {
                    String finalResult = result.toString();
                    logger.debug("Final processed result: {}", finalResult);
                    return finalResult;
                } else {
                    logger.error("No valid response content found in Coze API response");
                    return "抱歉，我无法回答这个问题。";
                }
            } else {
                logger.error("Failed to get response from Coze API: {}", response.getStatusCode());
                return "抱歉，我无法回答这个问题。";
            }
        } catch (Exception e) {
            logger.error("Error while calling Coze API", e);
            return "抱歉，我无法回答这个问题。";
        }
    }

    /**
     * 直连 Coze 工作流流式接口，并把每条事件通过 SseEmitter 转发给前端。
     * 事件名称尽量保持与 Coze 文档一致，例如 workflow_started、node_started、message、workflow_completed、error、done。
     */
    public void streamWorkflowEvents(String question, SseEmitter clientEmitter) {
        new Thread(() -> {
            // 回退到使用底层连接，确保逐行转发
            try {
                java.net.URL url = new java.net.URL(cozeApiUrl);
                java.net.HttpURLConnection conn = (java.net.HttpURLConnection) url.openConnection();
                conn.setRequestMethod("POST");
                conn.setDoOutput(true);
                conn.setRequestProperty("Content-Type", "application/json");
                conn.setRequestProperty("Accept", "text/event-stream");
                conn.setRequestProperty("Authorization", "Bearer " + cozeApiKey);

                Map<String, Object> body = new HashMap<>();
                body.put("app_id", appId);
                body.put("workflow_id", workflowId);
                Map<String, String> params = new HashMap<>();
                params.put("language_text", question);
                body.put("parameters", params);
                String json = objectMapper.writeValueAsString(body);

                try (java.io.OutputStream os = conn.getOutputStream()) {
                    byte[] input = json.getBytes(StandardCharsets.UTF_8);
                    os.write(input, 0, input.length);
                    os.flush();
                }

                int status = conn.getResponseCode();
                if (status != 200) {
                    clientEmitter.send(SseEmitter.event().name("error").data("上游返回状态码:" + status));
                    clientEmitter.complete();
                    conn.disconnect();
                    return;
                }

                try (java.io.InputStream is = conn.getInputStream();
                     java.io.BufferedReader reader = new java.io.BufferedReader(new java.io.InputStreamReader(is, StandardCharsets.UTF_8))) {
                    String line;
                    String lastEventName = null;
                    while ((line = reader.readLine()) != null) {
                        if (line.startsWith("event:")) {
                            lastEventName = line.substring(6).trim();
                            continue;
                        }
                        if (!line.startsWith("data:")) {
                            continue;
                        }
                        String payload = line.substring(5).trim();
                        if (payload.isEmpty()) {
                            continue;
                        }
                        if ("[DONE]".equals(payload) || "done".equalsIgnoreCase(payload)) {
                            clientEmitter.send(SseEmitter.event().name("done").data("done"));
                            break;
                        }
                        try {
                            JsonNode node = objectMapper.readTree(payload);
                            String jsonEvent = node.has("event") ? node.get("event").asText() : null;
                            String eventName = jsonEvent != null ? jsonEvent : (lastEventName != null ? lastEventName : "message");
                            clientEmitter.send(SseEmitter.event().name(eventName).data(payload));
                        } catch (Exception parseEx) {
                            String eventName = lastEventName != null ? lastEventName : "message";
                            clientEmitter.send(SseEmitter.event().name(eventName).data(payload));
                        }
                    }
                }

                clientEmitter.complete();
                conn.disconnect();
            } catch (Exception e) {
                try {
                    logger.error("SSE streaming error", e);
                    clientEmitter.send(SseEmitter.event().name("error").data("stream_error:" + e.getMessage()));
                } catch (Exception ignored2) {}
                clientEmitter.complete();
            }
        }, "coze-sse-forward-thread").start();
    }

    /**
     * 解析SSE事件数据
     *
     * @param eventText SSE事件文本
     * @return 包含事件类型和数据的Map
     */
    private Map<String, String> parseEventData(String eventText) {
        Map<String, String> result = new HashMap<>();
        String[] lines = eventText.split("\n");

        for (String line : lines) {
            line = line.trim();
            if (line.startsWith("id:")) {
                result.put("id", line.substring(3).trim());
            } else if (line.startsWith("event:")) {
                result.put("event", line.substring(6).trim());
            } else if (line.startsWith("data:")) {
                result.put("data", line.substring(5).trim());
            }
        }

        return result;
    }

    /**
     * 尝试解码可能被错误编码的Unicode字符串
     *
     * @param text 可能包含编码问题的文本
     * @return 解码后的文本
     */
    private String decodeUnicodeIfNeeded(String text) {
        if (text == null || text.isEmpty()) {
            return text;
        }

        try {
            // 检查是否包含乱码特征
            if (text.contains("ä") || text.contains("å") || text.contains("æ")) {
                // 尝试将ISO-8859-1编码的字符串转换为UTF-8
                byte[] bytes = text.getBytes(StandardCharsets.ISO_8859_1);
                return new String(bytes, StandardCharsets.UTF_8);
            }
        } catch (Exception e) {
            logger.warn("Failed to decode Unicode text: {}", e.getMessage());
        }

        return text;
    }

    public void setAppId(String appId) {
        this.appId = appId;
    }
}
